package com.company.service.impl;

import com.company.common.Constants;
import com.company.common.PageUtils;
import com.company.model.Banner;
import com.company.model.request.BannerQuery;
import com.company.model.result.PageResult;
import com.company.repository.BannerRepository;
import com.company.service.IBannerService;
import com.company.service.ICacheService;
import com.company.utils.JsonUtil;
import com.google.common.collect.Lists;
import com.google.gson.reflect.TypeToken;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

/**
 * Created by tu on 2017/7/11.
 */
@Service
public class BannerServiceImpl implements IBannerService {

  private static final Logger logger = LoggerFactory.getLogger(BannerServiceImpl.class);
  @Autowired
  BannerRepository repository;
  @Autowired
  ICacheService cacheService;

  @Override
  public PageResult<Banner> list(BannerQuery query) {
    PageResult<Banner> banners;

    final String key = Constants.REDIS_KEY_BANNERS_PREFIX + query.toString();
    Boolean exist = cacheService.exists(key);
    if (exist) {
      String value = cacheService.get(key);
      banners = JsonUtil.fromJson(value, new TypeToken<PageResult<Banner>>() {
      });
    } else {
      Specification<Banner> specification = initSpecification(query);
      PageRequest pageRequest = PageUtils.initPageRequest(query);
      logger
          .info("开始调用repository.findAll,参数{},{}", specification.toString(),
              pageRequest.toString());
      Page<Banner> bannerPage = repository
          .findAll(initSpecification(query), PageUtils.initPageRequest(query));
      logger.info("结束调用repository.findAll,参数{},{},结果{}",
          specification.toString(),
          pageRequest.toString(), bannerPage.toString());

      banners = PageUtils.wrapPageResult(bannerPage);
      cacheService.setex(key, Constants.REDIS_EXTIME_SECONDS,
          JsonUtil.toJson(banners));
    }
    return banners;
  }

  private Specification<Banner> initSpecification(final BannerQuery request) {
    return new Specification<Banner>() {
      @Override
      public Predicate toPredicate(Root<Banner> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        Predicate predicate = cb.conjunction();
        List<Expression<Boolean>> expressions = predicate.getExpressions();
        List<Order> orders = Lists.newArrayList();
        orders.add(cb.desc(root.<String>get("sort")));
        orders.add(cb.desc(root.<String>get("updateTime")));
        query.orderBy(orders);
        expressions.add(cb.equal(root.<String>get("deleted"), 0));
        return predicate;
      }
    };
  }
}
